package com.yazi.mxz.gather.main.goods;

import java.io.IOException;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;



import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText;
import com.yazi.mxz.gather.common.App;
import com.yazi.mxz.gather.common.App.PicObject;
import com.yazi.mxz.gather.entity.enums.ProcessType;
import com.yazi.mxz.gather.entity.http.JqbhResBody4Attr;
import com.yazi.mxz.gather.entity.http.JqbhResBody4List;
import com.yazi.mxz.gather.entity.http.JqbhResBody4Param;
import com.yazi.mxz.gather.entity.http.JqbhResBody4Pic;
import com.yazi.mxz.gather.entity.http.JqbhResBody4List.Li;
import com.yazi.mxz.gather.entity.http.JqbhResBody4Param.Td;
import com.yazi.mxz.gather.entity.http.JqbhResBody4Param.Tr;
import com.yazi.mxz.gather.entity.http.JqbhResBody4Pic.Img;
import com.yazi.mxz.gather.entity.repository.ProcessLog;
import com.yazi.mxz.gather.entity.repository.Product;
import com.yazi.mxz.gather.repository.ProcessLogRepository;
import com.yazi.mxz.gather.repository.ProductRepository;

/**
 * 坚强商城
 * http://jqbh.net
 * @author mo_yq5
 * @date 2015-8-15
 */
public class JqbhNet extends Thread {
	
	private CloseableHttpAsyncClient httpclient;
	private ProcessLogRepository logRepository;
	private ProductRepository productRepository;
	private ObjectMapper om;
	
	
	public JqbhNet() {
		init();
	}
	
	public JqbhNet(int startPage, int endPage) {
		init();
		ProcessLog log = logRepository.findOne(ProcessType.JQBH.ordinal());
		if (null == log) {
			log = new ProcessLog();
			log.setId(ProcessType.JQBH.ordinal());
			log.setCur((long)startPage);
			log.setEnd((long)endPage);
			log.setCount(0);
			logRepository.insert(log);
		} else {
			log.setCur((long)startPage);
			log.setEnd((long)endPage);
			logRepository.save(log);
		}
	}
	
	public void init() {
		
		productRepository = App.context.getBean(ProductRepository.class);
		logRepository = App.context.getBean(ProcessLogRepository.class);
		
		httpclient = HttpAsyncClients.createDefault();
		httpclient.start();
		
		om = new XmlMapper();
		om.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
	}

	@Override
	public void run() {
		
		ProcessLog log = logRepository.findOne(ProcessType.JQBH.ordinal());
		if (null == log) {
			System.out.println(ProcessType.JQBH + "日志不存在");
			return;
		}
		boolean isContinue = false;
		
		try {
			
			
			while (true) {
				
				if (log.getCur() > log.getEnd()) {
					isContinue = false;
					break;
				}
				
				barcodeInfo(log.getCur());
				
				log.setCur(log.getCur() + 1);
				logRepository.save(log);
			
				sleep(200);
			}
			
		} catch (SocketException e) {
			e.printStackTrace();
			isContinue = true;
			
		} catch (Exception e1) {
			e1.printStackTrace();
			
		} 
		if (isContinue) {
			run();
		} else {
			System.out.println("执行结束！");
		}
	}
	
	private String barcodeInfo(long pageNum) throws JsonParseException, JsonMappingException,
			IOException, InterruptedException, ExecutionException {
		
		System.out.println("PageNum:" + pageNum);
		
		final HttpPost req = new HttpPost("http://jqbh.net/index.php/gallery-ajax_get_goods.html?cat_id=&virtual_cat_id=&scontent=n&orderBy=&showtype=grid&page=" + pageNum);
		List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
		params.add(new BasicNameValuePair("cat_id", ""));
		params.add(new BasicNameValuePair("virtual_cat_id", ""));
		params.add(new BasicNameValuePair("scontent", "n"));
		params.add(new BasicNameValuePair("orderBy", ""));
		params.add(new BasicNameValuePair("showtype", "grid"));
		params.add(new BasicNameValuePair("page", "" + pageNum));
		req.setEntity(new UrlEncodedFormEntity(params));
		Future<HttpResponse> future = httpclient.execute(req, null);
		HttpResponse res = future.get();
		
		System.out.println(req.getRequestLine() + "->" + res.getStatusLine());
		
		StringBuffer bodySb = new StringBuffer(EntityUtils.toString(res.getEntity(), "utf-8"));
		if (bodySb.length() == 0) {
			System.out.println("无响应内容!");
			return null;
		}
		
		int start = bodySb.indexOf("<ul class=\"clearfix\">");// <ul class="clearfix">
		int end =  bodySb.indexOf("</ul>", start) + 5;		
		String listStr = bodySb.substring(start, end)
				.replaceAll("alt=\"[\\s|\\S]{0,50}style=\"max-width:180px;", "style=\"max-width:180px;") // 去掉alt, 名称内容可能含有特殊字符
				.replaceAll("<br>", "");

		
		// 去除注释<!-- -->
		String str = "<!--";
		while(true) {
			start = listStr.indexOf(str);
			if (start == -1) {
				break;
			} 
			listStr = listStr.replace(listStr.substring(start, listStr.indexOf("-->", start) + 3), "");
		}
		// 去除无用块<div class="promotion-tags">....</li> (不包括</li>)
		str = "<div class=\"promotion-tags\">";
		while(true) {
			start = listStr.indexOf(str);
			if (start == -1) {
				break;
			} 
			listStr = listStr.replace(listStr.substring(start, listStr.indexOf("</li>", start)), "");
		}
		
		StringBuffer listSb = new StringBuffer(listStr);
		
		// 给所有img标签补上/结束符
		start = 0;
		while(true) {
			start = listSb.indexOf("<img", start);
			if (start == -1) {
				break;
			}
			end = listSb.indexOf(">", start);
			listSb.insert(end, "/");
			start = end;
		}
		
		// 所有名称用<![CDATA[...]]>包裹
		str = "<h3 class=\"goods-name\"><a ";
		start = 0;
		while(true) {
			start = listSb.indexOf(str, start);
			if (start == -1) {
				break;
			}
			start = listSb.indexOf(">", start + str.length()) + 1;
			listSb.insert(start, "<![CDATA[");
			end = listSb.indexOf("</a>", start);
			listSb.insert(end, "]]>");
			start = end;
		}
		
		listStr = listSb.toString();
		
		//System.out.println(listStr);
		JqbhResBody4List jqbh4List = om.readValue(listStr, JqbhResBody4List.class);
		List<Li> lis = jqbh4List.getLis();
		StringBuffer goodsInfo = new StringBuffer();
		String detailUrl, name, barcode, pic, price, catName, brandName, mkPrice, bigPic;
		for (Li li : lis) {
			
			pic = li.getDivs().get(0).getA().getImg().getSrc();// 图片
			if (pic.equals("http://jqbh.net/public/images/18/9f/44/580eec353ac3eb23588bcc121c1d568b.gif?1386682852#h")) {
				pic = null;
			}
			detailUrl = li.getDivs().get(1).getH3().getA().getHref();// 详情地址如: /index.php/product-34850.html
			detailUrl = "http://jqbh.net" + detailUrl;
			name = li.getDivs().get(1).getH3().getA().getText().trim(); // 名称
			price = li.getDivs().get(1).getDiv().getIns().getText().replace("￥", "").trim();// 价格
			mkPrice = li.getDivs().get(1).getDiv().getDel().getText().replace("￥", "").trim();// 市场价
			
			
			Map<String, String> detail = getDetailInfo(detailUrl);
			
			barcode = detail.get("barcode");
			catName = detail.get("catName");
			brandName = detail.get("brandName");
			bigPic = detail.get("bigPic");
			
			if (null == barcode || !App.checkBarCode(barcode)) {
				System.out.println("无效条码: " + barcode + " -> " + name);
				continue;
			}
			
			goodsInfo = new StringBuffer();
			goodsInfo.append("\r\nUrl:" + detailUrl);
			goodsInfo.append("\r\n条码:" + barcode);
			goodsInfo.append("\r\n名称:" + name);
			goodsInfo.append("\r\n单价:" + price);
			goodsInfo.append("\r\n市场价:" + mkPrice);
			goodsInfo.append("\r\n分类:" + catName);
			goodsInfo.append("\r\n品牌:" + brandName);
			goodsInfo.append("\r\n小图:" + pic);
			goodsInfo.append("\r\n大图:" + bigPic);
			System.out.println(goodsInfo);
			
			App.PicObject picObj = new App.PicObject();
			
			if (null != pic ) {
				App.setPic(pic, picObj);
			}
			if (null != bigPic ) {
				App.setPic(bigPic, picObj);
			}
			
			if (!productRepository.exists(barcode)) {
				
				System.out.println("添加: " + barcode + " -> " + name);
				
				
				Product product = new Product();

				//product.setArea(area);
				product.setBarcode(barcode);
				product.setBigPic(App.saveGoodsBigImageV1(picObj.getBigPic()));
				product.setBrandName(brandName);
				product.setCatName(catName);
				//product.setFacCode(items.getFacCode());
				//product.setFacName(items.getFacName());
				product.setIsCheckName(true);
				product.setMidPic(App.saveGoodsMiddleImageV1(picObj.getMidPic()));
				product.setName(name);
				//product.setSpell(rs.getString("pinyin"));
				product.setPic(App.saveGoodsImageV1(picObj.getPic()));
				product.setPrice(price);
				//product.setUnit(unit);
				product.setSource("jqbh.net");
				//product.setSpec(spec);
				//product.setSupplier(items.getSupplier());
				product.setSysRemark(detailUrl);

				productRepository.insert(product);

			} else {
				
				System.out.println("修改: " + barcode + " -> " + name);

				Product product = productRepository.findOne(barcode);
				
				// 图片无水印
				
				if (null == product.getBigPic() && null != (pic = (App.saveGoodsBigImageV1(picObj.getBigPic())))) {
					App.delGoodsImageV1(product.getBigPic());
					product.setBigPic(pic);
				}
				if (null == product.getMidPic() && null != (pic = (App.saveGoodsMiddleImageV1(picObj.getMidPic())))) {
					App.delGoodsImageV1(product.getMidPic());
					product.setMidPic(pic);
				}
				if (null != picObj.getPic() && null != (pic = (App.saveGoodsImageV1(picObj.getPic())))) {
					App.delGoodsImageV1(product.getPic());
					product.setPic(pic);
				}
				
				if (null != brandName && null == product.getBrandName()) {
					product.setBrandName(brandName);
				}
				if (null != catName && null == product.getCatName()) {
					product.setCatName(catName);
				}
				if (null != name && null == product.getName()) {
					product.setName(name);
				}
				if (null != price && null == product.getPrice()) {
					product.setPrice(price);
				}
				
				productRepository.save(product);

			}
		}
		
		return null;
	}
	
	private Map<String, String> getDetailInfo(String detailUrl) throws InterruptedException, ExecutionException, ParseException, IOException {

		final HttpGet req = new HttpGet(detailUrl);
		Future<HttpResponse> future = httpclient.execute(req, null);
		HttpResponse res = future.get();
		
		System.out.println(req.getRequestLine() + "->" + res.getStatusLine());
		
		StringBuffer bodySb = new StringBuffer(EntityUtils.toString(res.getEntity(), "utf-8"));
		if (bodySb.length() == 0) {
			System.out.println("无响应内容!");
			return new HashMap<String, String>();
		}
		
		String catName = null, brandName = null, barcode = null, bigPic = null;
		
		
		// 属性相关 <table></table>
		String str = "<div class=\"product-params\">";
		int start = bodySb.indexOf(str) + str.length();// <table>
		int end = bodySb.indexOf("</table>", start) + 8;// </table>
		String paramStr = bodySb.substring(start, end)
				.replaceAll("&", ""); // 品牌名有此字符
		
		//System.out.println(paramStr);
		JqbhResBody4Param jqbh4Param = om.readValue(paramStr, JqbhResBody4Param.class);
		List<Tr> trs = jqbh4Param.getTbody().getTrs();
		List<Td> tds;
		int size;
		for (Tr tr : trs) {
			tds = tr.getTds();
			size = tds.size();
			for (int i = 0; i< size; i++) {
				str = null;
				if (null != tds.get(i).getDiv()) {
					str = tds.get(i).getDiv().getText();
					if (null != str && str.trim().equals("货品编号：")) {
						barcode = tds.get(i + 1).getText().trim(); // 条码
					}
				}
				
				//..其它属性
				
				i++;// 跳过一个td,两个td为一组
			}
		}
		
		// 分类相关<ul></ul>
		str = "<div class=\"product-attributes\">";
		start = bodySb.indexOf(str) + str.length();// <ul>
		end = bodySb.indexOf("</ul>", start) + 5;// </ul>
		String attrStr = bodySb.substring(start, end)
				.replaceAll("<li>", "<li><![CDATA[")
				.replaceAll("</li>", "]]></li>");
		
		//System.out.println(attrStr);
		JqbhResBody4Attr jqbh4Attr = om.readValue(attrStr, JqbhResBody4Attr.class);
		List<com.yazi.mxz.gather.entity.http.JqbhResBody4Attr.Li> lis = jqbh4Attr.getLis();
		for (com.yazi.mxz.gather.entity.http.JqbhResBody4Attr.Li li : lis) {
			if (li.getText().indexOf("所属分类：") > -1) {
				catName = li.getText().replaceAll("所属分类：", "").trim();// 分类
				
			} else if (li.getText().indexOf("品牌：") > -1) {
				try {
					brandName = om.readValue(li.getText().replaceAll("品牌：", ""), A.class).getText().trim();// 分类
				} catch (Exception e) {
					brandName = null;
				}
			}
			// ...其它属性else if
		}
		
		// 大图相关<textarea></textarea>
		str = "<div class=\"detail-content\">";
		start = bodySb.indexOf(str) + str.length();// <textarea>
		end = bodySb.indexOf("</textarea>", start) + 11;// </textarea>
		StringBuffer picSb = new StringBuffer(bodySb.substring(start, end));
		
		if (picSb.indexOf("<img") > -1 || picSb.indexOf("<IMG") > -1) {
			
			// 给所有img标签补上/结束符
			start = 0;
			while(true) {
				start = picSb.indexOf("<img", start);
				if (start == -1) {
					break;
				}
				end = picSb.indexOf(">", start);
				picSb.insert(end, "/");
				start = end;
			}
			start = 0;
			while(true) {
				start = picSb.indexOf("<IMG", start);
				if (start == -1) {
					break;
				}
				end = picSb.indexOf(">", start);
				picSb.insert(end, "/");
				start = end;
			}
			String picStr = picSb.toString()
					.replaceAll("&nbsp;", "")
					.replaceAll("IMG", "img");
			
			//System.out.println(picStr);
			try {
				JqbhResBody4Pic jqbh4Pic = om.readValue(picStr, JqbhResBody4Pic.class);
				List<Img> imgs = jqbh4Pic.getImgs();
				if (null != imgs && imgs.size() == 1) {
					bigPic = imgs.get(0).getSrc(); // 大图
				}
			} catch(Exception e) {
				System.out.println("bigPic:" + e.getMessage());
				bigPic = null;
			}
			
		}
		
		
		Map<String, String> detail = new HashMap<String, String>();
		detail.put("barcode", barcode);
		detail.put("catName", catName);
		detail.put("brandName", brandName);
		detail.put("bigPic", bigPic);
		return detail;
	}
	
	/**
	 * 品牌
	 */
	public static class A {
		@JacksonXmlText
		String text;

		public String getText() {
			return text;
		}

		public void setText(String text) {
			this.text = text;
		}
	}
}
